//Linux C plus plus file
/************************************************************************
*
*
*       			FileName:connection.cpp
*
*         			Author.wzj
*
*       			Email:345517039@qq.com
*
*      	    		Create:2017-06-22 23:45:06
*
*      		    	Description:-
*
*
*************************************************************************/
#include "connection.h"

#define CONNECTION_INIT_SIZE  1 << 17



/**
 * @brief 
 */
ConnectionSet::ConnectionSet(){
	this->hashTable = NULL;
	this->free_list = NULL;
	this->hashnum = 0;
}


/**
 * @brief 
 */
ConnectionSet::~ConnectionSet(){
	if ( NULL != this->hashTable)
	{

	}
	if ( NULL != this->free_list)
	{
		delete(this->free_list);
		this->free_list = NULL;
	}
	this->hashnum = 0;
}


/**
 * @brief 
 *
 * @return 
 */
int ConnectionSet::init(){
	int iRet = RET::FAIL;
	this->hashnum = CONNECTION_INIT_SIZE;
	this->mem.init(CONNECTION_LEVEL);
	struct Mem_t *temp = NULL;
	try
	{
		temp = this->mem.allocateMemFromMempool(sizeof(struct connection *)*hashnum);
	}
	catch(std::bad_alloc)
	{
		return iRet;
	}
	if(temp&& temp->addr)
		memset(temp->addr, '\0', sizeof(struct connection *)*hashnum);
	hashTable = (struct connection **)(temp->addr);
#ifdef __DEBUG_ON__
	for(size_t i =  0; i < this->hashnum ; i++)
	{
		std::cout << hashTable[i] << std::endl;
	}
#endif 
	//这边理论上要进行一个初始化;
	this->freeNodeListCount=0;
	this->free_list = NULL;
	return RET::SUCCESS;
}


/**
 * @brief 
 *
 * @param fd
 *
 * @return 
 */
int ConnectionSet::growHashTable(size_t fd){
	if(fd < 0){
		return -1;
	}
	int currSize = this->hashnum;
	if( fd > this->hashnum){
		while(fd > this->hashnum){
			this->hashnum = this->hashnum << 1;
		}
		//struct connection **temp = new struct connection *[this->hashnum];
		struct Mem_t * temp= this->mem.allocateMemFromMempool(sizeof(struct connection *)*hashnum);
		//这个开销可能会比较大,随着你这个连接越来越多的时候
		memcpy(temp->addr,*(this->hashTable), currSize*sizeof(struct connection *));
		this->hashTable = (struct connection **)(temp->addr);
		return 1;
	}else{
		return 0;
	}
}


/**
 * @brief 
 *
 * @param fd
 *
 * @return 
 */
int ConnectionSet::deleteFreeConnection(size_t fd){
	if(fd <0||fd >= this->hashnum){
		return -1;
	}
	if(this->hashTable[fd]){ //哈希表挂载的是关于这个连接所有的缓存数据
		struct connection * temp = this->hashTable[fd];
		this->hashTable[fd] = NULL;
		//这边设置一个门限值; 对内存块进行遍历
		if(this->freeNodeListCount >= CONNECTION_INIT_SIZE){
			
		}else{
			if(this->free_list == NULL){
				this->free_list = temp;
			}else{
				temp->next = this->free_list->next;
				this->free_list = temp;
			}		
		}
		return  1;
	}
	return 0;
}


/**
 * @brief 
 *
 * @param arg
 *
 * @return 
 */
size_t ConnectionSet::readDataFromConnNonblock(void *arg){
	struct connection * temp = (struct connection *)arg;
	size_t len = 0;
	size_t readed = 0;
	while(len < temp->bufsize&&len > 0 ){
		len = recv(temp->fd, temp->readbuf+readed,temp->bufsize - readed, 0);
		if(len > 0){
			readed+=len;
		}else if( len == 0){
			//对端已经关闭;
			break;
		}else if( len < 0){
			if( errno == EWOULDBLOCK || errno == EAGAIN)
			{
				continue;
			}else{
				//其他错误;
				break;
			}
		}
	}
	return readed; 
}



